% Ejercicio "Paso de parámtros en WWW"
\subsection*{\fbox{\theejercicio} - Paso de par\'ametros en WWW}

En los servidores WWW existe un mecanismo mediante el cual, un servidor es capaz de obtener los valores que un usuario de un cliente Web ha introducido en un formulario. El cliente Web env\'{\i}a al servidor una cadena denominada QUERY\_STRING con un determinado formato. Dicho formato es aproximadamente el siguiente:

$$nombre_1=[valor_1]\ sep\ nombre_2=[valor_2]\ sep\ \cdots\ nombre_n = [valor_n]\ [sep]$$

en donde $nombre$ es un identificador similar a los del lenguaje C; $valor$ puede ser:
\begin{itemize}
\item Una cadena de caracteres ASCII entre comillas, del tipo ``$secuencia\_de\_caracteres$''.  En esta $secuencia\_de\_caracteres$ no debe aparecer el propio car\'acter '', ni el caracter blanco, ni tabuladores, ni saltos de l\'{\i}nea.
\item Una constante entera.
\end{itemize}

y $sep$ (separador) consiste en una secuencia no vac\'{\i}a de \&.

Los corchetes que aparecen en esta descripci\'on  indican que lo que contienen es opcional. Cuando valor es una cadena, el espacio en blanco es sustituido por el caracter +, y caracteres especiales (\'a\'e\'{\i}\'o\'u\~n\~N...) son sustituidos por  $\%HH$, donde  $HH$ es el valor hexadecimal ASCII del car\'acter correspondiente. 

\smallskip

Se pide construir un programa LEX/YACC que acepte una l\'{\i}nea con este formato, que guarde dicha informaci\'on en la tabla de s\'{\i}mbolos, y que finalmente genere una salida donde se imprima el valor asociado a cada nombre (siempre y cuando dicho valor no sea nulo). Por ejemplo:

\begin{center}
\begin{tabular}{|l|} \hline
ENTRADA                                                                    \\ \hline
\verb@departamento="Matem%A0ticas" && empleado="Jos%82+Antonio+L%A2pez" &@ \\
\verb@sueldo=15000 & hijos= &antig= & codigo="E700"&@                      \\ \hline
SALIDA                                                                     \\ \hline
\verb@departamento: "Matem@{\tt \'a}\verb@ticas"@                          \\
\verb@empleado: "Jos@{\tt \'e} \verb@Antonio L@{\tt \'o}\verb@pez"@        \\
\verb@sueldo: 15000@                                                       \\
\verb@codigo "E700"@                                                       \\ \hline
\end{tabular}
\end{center}


NOTAS:
\begin{itemize}
\item La tabla de s\'{\i}mbolos se define en C mediante la estructura que aparece al margen. El primer campo contiene el  nombre. El campo {\tt tipo} contiene los c\'odigos NUM o TIRA. El campo {\tt union} contiene bien un n\'umero entero, o bien una cadena de caracteres, seg\'un el contenido del campo {\tt tipo}. La variable  {\tt Primer\_libre} debe ser usada para controlar el primer \'{\i}ndice de la tabla de s\'{\i}mbolos v\'alido para guardar nueva informaci\'on.

\item Se supone que existe una funci\'on denominada \verb@tratar_valor(char *)@ que convierte las  secuencias de caracteres sustituyendo  $\%HH$ por el car\'acter correspondiente en el c\'odigo ASCII, y el car\'acter + por un espacio en blanco.

\item La uni\'on de YACC podr\'{\i}a ser la siguiente:
\begin{verbatim}
# define MAX_SIMBOLOS 40
typedef struct simbolo {
    char *nombre;
    int tipo;
    union {
       int num;
       char *tira;
    }u;
} SIMBOLO;

SIMBOLO tb_simbolos[MAX_SIMBOLOS];
int Primer_libre = 0;

%union {
    int indice;
    char *tira;
    int num;
}
\end{verbatim}
\end{itemize}

% Solución del ejercicio
\subsubsection*{SOLUCI\'ON}

\underline{ESPECIFICACI\'ON LEX}:

\begin{verbatim}
%{
#include "yytab.h"
#include "simbol.h"
extern SIMBOL tb_simbol[MAX_SIMBOL];
char *pedir_mem(int);
int instalar(char *);
int buscar(char *);

extern int Primer_libre;
%}

letra [A-Za-z]
dig [0-9]

%%

[ \t\n]+               {;}
[&]+                   { return '&'; }
[A-za-z_][0-9A-za-z_]* { if ((yylval.indice=buscar(yytext)) == -1 ) {
                            yylval.indice=instalar(yytext);
                         }
                         return (ID);
                       }
\"[^\"\ \t\n]*\"       { yylval.tira=pedir_mem(yyleng+1);
                         strcpy(yylval.tira,yytext);
                         return TIRA;
                       }
{dig}+                 { sscanf(yytext,"%d",&yylval.num);
                         return NUM;
                       }
=                      {return '=';}
.                      {;}

%%

char * pedir_mem(int tam) {
   /* ... devuelve un puntero en caso de que haya memoria 
      disponible ... */
}

int instalar (char * cad) {
   /* ... introduce un nombre en la tabla de simbolos ... */
}
int buscar (char * cad) {
   /* ... devuelve 1 si cad esta en la tabla de simbolos
      y-1encasocontrario...*/
}
\end{verbatim}

\underline{ESPECIFICACI\'ON YACC}:

\begin{verbatim}
%{
# include "simbol.h"
# define NULL (void *)0
int Primer_libre=0;
SIMBOL tb_simbol[MAX_SIMBOL];
extern char * pedir_mem(int);
void main(void);
void imprimir(void);
void yyerror(char *);
%}

%union {
   int indice;
   char * tira;
   int num;
}

%token <indice> ID
%token <tira> TIRA
%token <num> NUM
%start query

%%

query : list { imprimir(); }
      | list '&' { imprimir(); }
      ;
list  : asign
      | list '&' asign
      ;
asign : ID `=' { tb_simbol[$1].tipo=TIRA; tb_simbol[$1].u.tira=NULL; }
      | ID `=' NUM { tb_simbol[$1].tipo=NUM; tb_simbol[$1].u.num=$3; }
      | ID `=' TIRA { tb_simbol[$1].tipo=TIRA;
                      $3=tratar_tira($3);
                      tb_simbol[$1].u.tira=$3;
                    }
      ;

%%

void main() { yyparse(); }

void yyerror(char *cad) { printf("%s\n",cad); }

void imprimir() {
   /* ... produce un listado de la tabla de simbolos ...*/
}

char *tratar_tira(char * cad) {
   /* ... convierte las secuencias de caracteres, sustituyendo %HH
      por el caracter ASCII correspondiente y + por blanco ... */
}
\end{verbatim}

\underline{FICHERO simbol.h}:

\begin{verbatim}
# define MAX_SIMBOL 40
typedef struct simbol {
   char *nombre;
   int tipo;
   union {
      int num;
      char *tira;
   }u;
}SIMBOL;
\end{verbatim}